package com.newly.center.sys.service.dict.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.newly.center.sys.service.dict.api.IDictService;
import com.newly.center.sys.service.tenant.impl.TenantService;
import com.newly.common.base.constants.CodeConstant;
import com.newly.common.base.entity.PageUtils;
import com.newly.common.base.entity.auth.ICurrentTenant;
import com.newly.common.base.entity.sys.dict.dto.CreateDictDto;
import com.newly.common.base.entity.sys.dict.dto.DictTypeDto;
import com.newly.common.base.entity.sys.dict.dto.UpdDictDto;
import com.newly.common.base.entity.sys.dict.po.DictPo;
import com.newly.common.base.entity.sys.dict.po.DictTypePo;
import com.newly.common.base.entity.sys.dict.vo.TenantDictVo;
import com.newly.common.base.entity.sys.dict.vo.UpdDictVo;
import com.newly.common.base.entity.sys.tenant.po.TenantPo;
import com.newly.common.base.exception.NewlyDBException;
import com.newly.common.base.exception.NewlyException;
import com.newly.transfer.redis.RedisTransfer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author gjm guan
 * @date 2021/11/9 16:29
 * @desc 字典业务实现
 */
@Service
@Slf4j
public class DictService extends AbstractDictService implements IDictService {

    @Autowired
    private TenantService tenantService;

    @Autowired
    private RedisTransfer redisTransfer;

    @Override
    public boolean keyDuplicate(String code) {
        DictPo dictPo = dictMapper.selectOne(
                Wrappers.lambdaQuery(DictPo.class)
                        .eq(DictPo::getCode, code)
        );
        return ObjectUtil.isNotNull(dictPo);
    }

    @Override
    public UpdDictVo queryDictById(Integer id) {
        DictPo dictPo = dictMapper.selectOne(
                Wrappers.lambdaQuery(DictPo.class)
                        .eq(DictPo::getId, id)
                        //不查系统内置参数
                        .ne(DictPo::getType, 0)
        );
        return ObjectUtil.isNull(dictPo) ? null : BeanUtil.copyProperties(dictPo,UpdDictVo.class);
    }

    @Override
    public boolean createDict(ICurrentTenant currentTenant, CreateDictDto dictDto) {
        Assert.notNull(dictDto, "字典数据异常");
        Assert.notBlank(dictDto.getCode(), "code不能为空");
        Assert.notBlank(dictDto.getName(), "name不能为空");
        Assert.notBlank(dictDto.getValue(), "value不能为空");

        DictPo dictPo = BeanUtil.copyProperties(dictDto, DictPo.class);
        DateTime date = DateUtil.date();
        dictPo.setCreateTenantId(currentTenant.getUserId())
                .setType(3)
                .setCreateTime(date)
                .setUpdateTime(date);

        int result = 0;
        try {
            result = dictMapper.insert(dictPo);
        } catch (Exception e) {
            throw new NewlyDBException("字段入库异常： " + e);
        }

        return result > 0;
    }

    @Override
    public boolean createGoodType(ICurrentTenant currentTenant, String goodType) {
        if (StrUtil.isBlank(goodType)) {
            throw new NewlyException(CodeConstant.FAILED, "货物类型为空");
        }
        DateTime date = DateUtil.date();
        DictPo dictPo = new DictPo()
                .setCreateTime(date)
                .setUpdateTime(date)
                .setCreateTenantId(currentTenant.getUserId())
                .setName("企业源头货物类型")
                .setCode(goodType)
                .setValue(goodType)
                .setType(4);

        int insert = 0;
        try {
            insert = dictMapper.insert(dictPo);
        } catch (Exception e) {
            e.printStackTrace();
            String msg = e.getMessage();
            if (msg.contains("DuplicateKeyException")){
                throw new NewlyException(CodeConstant.FAILED,"该货物类型已存在");
            }
        }
        return insert > 0;
    }

    @Override
    public List<String> getGoodType() {
        List<String> list = dictMapper.selectList(
                Wrappers.lambdaQuery(DictPo.class)
                        .select(DictPo::getValue)
                        .eq(DictPo::getType, 4)
        ).stream()
                .map(DictPo::getValue).collect(Collectors.toList());

        if (ObjectUtil.isEmpty(list)) {
            return new ArrayList<>(0);
        }
        return list;
    }

    @Override
    public List<TenantDictVo> queryTenantOfCreateDict() {
        List<DictPo> dictPos = this.selectDict(null);
        if (ObjectUtil.isEmpty(dictPos)) {
            return null;
        }
        // 租户id
        List<Long> tenantIds = dictPos.stream().map(DictPo::getCreateTenantId)
                .collect(Collectors.toList());
        // 租户详情信息
        List<TenantPo> tenantPos = tenantService.getByIds(tenantIds);
        List<TenantDictVo> tenantDictVos = null;
        if (!ObjectUtil.isEmpty(tenantPos)) {
            tenantDictVos = tenantPos.stream().map(TenantDictVo::new)
                    .collect(Collectors.toList());
        }
        return tenantDictVos;
    }

    @Override
    public PageUtils listDict(String keyword, Integer offset, Integer limit, String startTime, String endTime) {

        IPage<DictPo> page = null;
        LambdaQueryWrapper<DictPo> wrapper = new LambdaQueryWrapper<>();
        //不查系统内置参数
        wrapper.and(w ->
                w.ne(DictPo::getType, 0)
                        .or().isNull(DictPo::getType)
        ).orderByDesc(DictPo::getCreateTime);

        // 分页
        if (ObjectUtil.isNotEmpty(offset) && ObjectUtil.isNotEmpty(limit)) {
            page = new Page<>(offset, limit);
        }

        // 关键字
        if (StrUtil.isNotBlank(keyword)) {
            wrapper.like(DictPo::getName, keyword);
        }

        // 创建时间段
        if (StrUtil.isNotBlank(startTime) && StrUtil.isNotBlank(endTime)) {
            wrapper.between(DictPo::getCreateTime, DateUtil.parse(startTime), DateUtil.parse(endTime));
        }

        return this.selectDict(page, wrapper);
    }

    @Override
    public List<DictPo> listAllDict(String keyword, String startTime, String endTime) {
        List<DictPo> list = this.selectDict(
                Wrappers.lambdaQuery(DictPo.class)
                        .ne(DictPo::getType, 0)
                        .orderByDesc(DictPo::getCreateTime)
                        .like(StrUtil.isNotBlank(keyword), DictPo::getName, keyword)
                        .between(StrUtil.isAllNotBlank(startTime, endTime),
                                DictPo::getCreateTime, DateUtil.parse(startTime), DateUtil.parse(endTime))
        );

        return list;
    }

    @Override
    public boolean removeDict(List<String> dictIds) {
        return this.deleteDict(dictIds);
    }

    @Override
    public boolean modifyDict(UpdDictDto dictDto) {
        Assert.notNull(dictDto, "字典数据异常");
        Assert.notNull(dictDto.getId(), "字典id不能为空");

        DictPo dictPo = BeanUtil.copyProperties(dictDto, DictPo.class);
        dictPo.setUpdateTime(DateUtil.date());

        return this.updateDict(dictPo);
    }

    @Override
    public PageUtils listDictType(String keyword, Integer offset, Integer limit, String startTime, String endTime) {

        LambdaQueryWrapper<DictTypePo> wrapper = new LambdaQueryWrapper<>();
        IPage<DictTypePo> page = null;

        // 关键字
        if (!StrUtil.isBlank(keyword)) {
            wrapper.like(DictTypePo::getName, keyword);
        }

        // 分页
        if (!ObjectUtil.isEmpty(offset) && !ObjectUtil.isEmpty(limit)) {
            page = new Page<>(offset, limit);
        }

        // 创建时间
        if (!StrUtil.isBlank(startTime) && !StrUtil.isBlank(endTime)) {
            wrapper.between(DictTypePo::getCreateTime, DateUtil.parse(startTime), DateUtil.parse(endTime));
        }

        return this.selectDictType(page, wrapper);
    }

    @Override
    public List<DictTypePo> queryDictType() {
        return this.selectDictType(null);
    }

    @Override
    public boolean removeDictType(List<String> dictTypeIds) {
        return this.deleteDictType(dictTypeIds);
    }

    @Override
    public boolean createDictType(DictTypeDto dictTypeDto) {
        Assert.notNull(dictTypeDto, "字典类型数据异常");
        Assert.notBlank(dictTypeDto.getName(), "name不能为空");

        DictTypePo dictTypePo = BeanUtil.copyProperties(dictTypeDto, DictTypePo.class);
        dictTypePo.setCreateTime(DateUtil.date());

        int result = 0;
        try {
            result = dictTypeMapper.insert(dictTypePo);
        } catch (Exception e) {
            throw new NewlyDBException("字典类型入库失败: " + e);
        }

        return result > 0;
    }

    @Override
    public boolean modifyDictType(DictTypeDto dictTypeDto) {
        Assert.notNull(dictTypeDto, "字典类型数据异常");
        Assert.notNull(dictTypeDto.getId(), "id不能为空");
        Assert.notBlank(dictTypeDto.getName(), "name不能为空");

        DictTypePo dictTypePo = BeanUtil.copyProperties(dictTypeDto, DictTypePo.class);

        return this.updateDictType(dictTypePo);
    }

    @Override
    public void refreshCache() {
        List<DictPo> dictPoList = this.dictMapper.selectList(new QueryWrapper<>());
        if (ObjectUtil.isEmpty(dictPoList))
            return;
        this.redisTransfer.setSysDic(dictPoList);
    }
}
